package com.youxin.chat.pay.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youxin.base.BaseResultCode;
import com.youxin.chat.pay.dto.CashStatusChange;
import com.youxin.chat.pay.entity.req.UserOrderReq;
import com.youxin.chat.pay.entity.vo.OrderDetailVo;
import com.youxin.chat.pay.entity.vo.UserOrderItem;
import com.youxin.chat.pay.entity.vo.UserOrderVo;
import com.youxin.chat.pay.enums.CashStatusEnum;
import com.youxin.chat.pay.enums.OrderSourceEnum;
import com.youxin.chat.pay.enums.OrderStatusEnum;
import com.youxin.chat.pay.mapper.*;
import com.youxin.chat.pay.model.*;
import com.youxin.chat.pay.service.OrderService;
import com.youxin.chat.pay.service.UserPayService;
import com.youxin.chat.pay.service.manager.UserCashManager;
import com.youxin.exception.SystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * description: OrderServiceImpl <br>
 * date: 2020/3/1 11:07 <br>
 * author: llkj <br>
 * version: 1.0 <br>
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Resource
    private CommonOrderMapper commonOrderMapper;

    @Resource
    private UserRechargeMapper userRechargeMapper;

    @Resource
    private UserCashManager userCashManager;

    @Resource
    private UserCashMapper userCashMapper;

    @Resource
    private UserCardMapper userCardMapper;

    @Resource
    private BankInfoMapper bankInfoMapper;

    @Resource
    private UserPayService userPayService;



    @Override
    public UserOrderVo getCommonOrderList(String userNo, UserOrderReq commonOrderRequest) {
        UserOrderVo orderDto = new UserOrderVo();
        if (!StringUtils.isEmpty(commonOrderRequest.getTime())) {
            commonOrderRequest.setStart(commonOrderRequest.getTime());
            try {
                Calendar rightNow = Calendar.getInstance();
                rightNow.setTime(new SimpleDateFormat("yyyy-MM").parse(commonOrderRequest.getTime()));
                rightNow.add(Calendar.MONTH, 1);
                commonOrderRequest.setEnd(new SimpleDateFormat("yyyy-MM").format(rightNow.getTime()));
            } catch (Exception e) {
                logger.error("日期时间出错");
            }

        }
        List<UserOrderItem> list = commonOrderMapper.getCommonOrderList(new Page<>(commonOrderRequest.getCurrentPage(),commonOrderRequest.getShowCount()),userNo, commonOrderRequest);

        BigDecimal income = Optional.ofNullable(commonOrderMapper.getOrderAmount(0,userNo,commonOrderRequest)).orElse(new BigDecimal(0));
        BigDecimal expend = Optional.ofNullable(commonOrderMapper.getOrderAmount(1,userNo,commonOrderRequest)).orElse(new BigDecimal(0));


        orderDto.setIncome(String.valueOf(income.setScale(0, BigDecimal.ROUND_HALF_UP)));
        orderDto.setExpend(String.valueOf(expend.setScale(0, BigDecimal.ROUND_HALF_UP)));

        list.stream().forEach((item) -> {
            if ( item.getOrderSource().equals(OrderSourceEnum.PAY.getStatus())){
                item.setOrderStatus(markExpiredOrder(item.getOrderStatus(),item.getCreateTime()));
            }
        });

        orderDto.setList(list);
        return orderDto;
    }

    @Override
    public OrderDetailVo getCommonOrderDetail(String userNo, String orderNo) {
        OrderDetailVo orderDetailDto = new OrderDetailVo();
        CommonOrder commonOrder = commonOrderMapper.selectByOrderNo(orderNo);
        UserRecharge userRecharge = new UserRecharge();
        UserCash userCash = new UserCash();
        int status = commonOrder.getOrderStatus();
        if (commonOrder.getOrderSource() == OrderSourceEnum.PAY.getStatus()) {
            userRecharge = userRechargeMapper.selectOne(new LambdaQueryWrapper<UserRecharge>().eq(UserRecharge::getRechargeNo, orderNo));
            status = markExpiredOrder(commonOrder.getOrderStatus(),commonOrder.getCreateTime());
        } else if (commonOrder.getOrderSource() == OrderSourceEnum.DEFRAY.getStatus()) {
            userCash = userCashMapper.selectOne(new LambdaQueryWrapper<UserCash>().eq(UserCash::getCashNo, orderNo));
        } else {
            orderDetailDto.setOrderNo(orderNo);
            orderDetailDto.setOrderAmount(commonOrder.getOrderAmount());
            orderDetailDto.setOrderSource(commonOrder.getOrderSource());
            orderDetailDto.setOrderStatus(commonOrder.getOrderStatus());
            return orderDetailDto;
        }
        String cardNo;
        if (!StringUtils.isEmpty(userRecharge.getCardNo())) {
            cardNo = userRecharge.getCardNo();
        } else if (!StringUtils.isEmpty(userCash.getCardNo())) {
            cardNo = userCash.getCardNo();
        } else {
            throw new SystemException(BaseResultCode.COMMON_FAIL, "银行卡号不存在");
        }
        UserCard userCard = userCardMapper.selectOne(new LambdaQueryWrapper<UserCard>().eq(UserCard::getUserNo, userNo).eq(UserCard::getCardNo, cardNo));
        BankInfo bankInfo = bankInfoMapper.selectOne(new LambdaQueryWrapper<BankInfo>().eq(BankInfo::getBankCode, userCard.getBankCode()));

        orderDetailDto.setCardName(bankInfo.getBankName());
        orderDetailDto.setCardNo(cardNo);
        orderDetailDto.setCreateTime(commonOrder.getCreateTime());
        orderDetailDto.setOpTime(commonOrder.getOpTime());
        orderDetailDto.setOrderAmount(commonOrder.getOrderAmount());
        orderDetailDto.setOrderRemark(commonOrder.getOrderRemark());
        orderDetailDto.setOrderSource(commonOrder.getOrderSource());
        orderDetailDto.setOrderStatus(status);
        orderDetailDto.setOrderNo(orderNo);
        if (orderDetailDto.getOrderStatus() == 0 && orderDetailDto.getCreateTime().isBefore(LocalDateTime.now().minusDays(1))) {
            orderDetailDto.setOrderStatus(-2);
        }
        return orderDetailDto;
    }

    @Override
    public void orderDel(String userNo, List<String> idList) {
        Collection<CommonOrder> list = commonOrderMapper.selectBatchIds(idList);
        List<String> ids = new ArrayList<>();
        list.stream().forEach(item -> {
            if (userNo.equalsIgnoreCase(item.getUserNo())) {
               ids.add(item.getId());
            }
        });
        commonOrderMapper.updateDisplayByIds(0,ids);
    }

    @Override
    public void changeCashStatus(CashStatusChange cashStatusChange) {
        UserCash userCash = userCashMapper.selectByCashNo(cashStatusChange.getOrderNo());
        if (userCash == null) {
            logger.error("订单号不存在，orderNo={}", cashStatusChange.getOrderNo());
           throw new SystemException(BaseResultCode.COMMON_FAIL, "订单号不存在");
        }
        if (CashStatusEnum.FAIL.getStatus().equals(userCash.getCashStatus()) || CashStatusEnum.SUCCESS.getStatus().equals(userCash.getCashStatus())) {
            logger.error("订单状态为完成状态，无法修改，orderNo={}", cashStatusChange.getOrderNo());
            throw new SystemException(BaseResultCode.COMMON_FAIL, "订单状态为完成状态，无法修改");

        }
        if (CashStatusEnum.SUCCESS.getStatus().equals(cashStatusChange.getStatus())) {
            userCashManager.doCashSuccess(userCash);
        } else if (CashStatusEnum.FAIL.getStatus().equals(cashStatusChange.getStatus())) {
            userCashManager.doCashFail(userCash);

        }
    }

    @Override
    public void syncCashStatus(Integer minute) {
        LocalDateTime time = LocalDateTime.now().minusSeconds(minute);
        List<String> cashNos = userCashMapper.selectProcessCash(time);
        for(String cashNo:cashNos){
            userPayService.defrayQuery(cashNo);
        }
    }

    @Override
    public void syncOrderStatus(String orderNo) {
        UserRecharge userRecharge = userRechargeMapper.selectOne(new LambdaQueryWrapper<UserRecharge>()
        .eq(UserRecharge::getRechargeNo,orderNo));
        userPayService.payQuery(orderNo);
    }

    @Override
    public void syncCashStatus(String orderNo) {
         userPayService.defrayQuery(orderNo);
    }

    private int markExpiredOrder(int status, LocalDateTime createTime){
        if (status == OrderStatusEnum.NOT_PAY.getStatus() && createTime.isBefore(LocalDateTime.now().minusSeconds(30))) {
            return OrderStatusEnum.EXPIRED.getStatus();
        }
        return status;
    }
}
